Ext.BLANK_IMAGE_URL = "./images/default/s.gif";

Ext.namespace("livcos");

livcos.ScrollLink = function() {
  this.nodes = new Array();
}

livcos.ScrollLink.prototype.add = function(node) {
  this.nodes[this.nodes.length] = node;
  node._scrollLink = this;
  Ext.EventManager.addListener(node, "scroll", function(evn) {
    var s = this._scrollLink;
    var v = livcos.ScrollLink.readPositioning(this);
    var ph = v.scrollTop / (v.scrollHeight - v.height);
    for (var i = 0; i < s.nodes.length; ++i) {
      var e = s.nodes[i];
      if (e == this)
        continue;
      var v = livcos.ScrollLink.readPositioning(e);
      var d = (v.scrollHeight - v.height) * ph;
      if ((Math.abs(v.scrollTop - d) > 0.5)) {
        if (e.scrollTo)
          e.scrollTo(0, Math.round(d));
        else
          e.scrollTop = Math.round(d);
      }
    }
  });
}

livcos.ScrollLink.prototype.remove = function(node) {
  this.nodes.remove(node);
}

livcos.ScrollLink.readPositioning = function(e) {
  var p = new Object();
  if (e.document)
    e = e.document.documentElement;
  p.scrollTop = e.scrollTop;
  p.scrollHeight = e.scrollHeight;
  p.height = e.offsetHeight;
  return p;
}


livcos.HistoryPreviewLink = function(preview1, preview2) {
  this.preview1 = preview1;
  this.preview2 = preview2;
  this.scrollLink = new livcos.ScrollLink();
  this.preview1.previewLink = this;
  this.preview2.previewLink = this;
}

livcos.HistoryPreviewLink.prototype.update = function() {
  var p1 = this.preview1.iframeEl.dom.contentWindow;
  var p2 = this.preview2.iframeEl.dom.contentWindow;
  if (!p1 || !p2)
    return;
  if (this.oldP1 != p1) {
    this.scrollLink.remove(this.oldP1);
    this.oldP1 = p1;
  }
  if (this.oldP2 != p2) {
    this.scrollLink.remove(this.oldP2);
    this.oldP2 = p2;
  }
  this.scrollLink.add(p1);
  this.scrollLink.add(p2);
  livcos.HistoryPreviewLink.clear(p1.document.body);
  livcos.HistoryPreviewLink.clear(p2.document.body);
  livcos.HistoryPreviewLink.compareAndMark(p1.document.body, p2.document.body);
}

livcos.HistoryPreviewLink.mark = function(node, color) {
  if (!node)
    return;
  if (node.style) {
    if (!node._originalStyle) {
      node._originalStyle = new Object();
      node._originalStyle.backgroundColor = node.style.backgroundColor;
    }
    node.style.backgroundColor = color;
  }
  else {
    var m = node.ownerDocument.createElement("span");
    node.parentNode.replaceChild(m, node);
    m.appendChild(node);
    m.style.backgroundColor = color;
    m._markerNode = node;
  }
}

livcos.HistoryPreviewLink.markPlaceholder = function(node) {
  if (!node)
    return;
  node._placeholder = true;
  if (node.style) {
    node.style.visibility = "hidden";
  }
  else {
    var m = node.ownerDocument.createElement("span");
    node.parentNode.replaceChild(m, node);
    m.appendChild(node);
    m.style.visibility = "hidden";
    m._markerNode = node;
  }
}

livcos.HistoryPreviewLink.unmark = function(node) {
  if (!node)
    return;
  if (node._originalStyle) {
    node.style.backgroundColor = node._originalStyle.backgroundColor;
    node._originalStyle = null;
  }
  if (node._markerNode) {
    node.parentNode.replaceChild(node._markerNode, node);
    node._markerNode = null;
  }
}

livcos.HistoryPreviewLink.clear = function(parentNode) {
  if (!parentNode)
    return;
  for(var i = parentNode.childNodes.length - 1; i >= 0; --i) {
    var n = parentNode.childNodes[i];
    livcos.HistoryPreviewLink.unmark(n);
	  if (n._placeholder)
	    n.parentNode.removeChild(n);
	  else
      livcos.HistoryPreviewLink.clear(n);
  }
    
}

livcos.HistoryPreviewLink.compareAndMark = function(parentNode1, parentNode2) {
  if (!parentNode1 || !parentNode2)
    return;
  for(var i1 = 0, i2 = 0; (i1 < parentNode1.childNodes.length) || (i2 < parentNode2.childNodes.length); ++i1, ++i2) {
    var n1 = (i1 < parentNode1.childNodes.length)?parentNode1.childNodes[i1]: null;
    var n2 = (i2 < parentNode2.childNodes.length)?parentNode2.childNodes[i2]: null;
    if (n1 && !n2) {
    	n2 = n1.cloneNode(true);
    	parentNode2.appendChild(n2);
      livcos.HistoryPreviewLink.mark(n1, "yellow");
      livcos.HistoryPreviewLink.markPlaceholder(n2);
    }
    else if (!n1 && n2) {
      n1 = n2.cloneNode(true);
      parentNode1.appendChild(n1);
      livcos.HistoryPreviewLink.mark(n2, "yellow");
      livcos.HistoryPreviewLink.markPlaceholder(n1);
    }
    else {
      if (n1.nodeValue != n2.nodeValue) {
        livcos.HistoryPreviewLink.mark(n1, "#44FF44");
        livcos.HistoryPreviewLink.mark(n2, "#44FF44");
      }
      else {
        livcos.HistoryPreviewLink.compareAndMark(n1, n2);
      }
    }
  }
    
}

livcos.HistoryPreviewLink.compare = function(parentNode1, parentNode2) {
  var i;
  // copy or create new attributes
  var attrs = this.dom.attributes;
  for(i = 0; i < attrs.length; ++i) {
    var a = attrs[i];
    var ta = targetDom.getAttributeNode(a.name);
    if (!ta || (ta.value != a.value)) {
//      debug("set " +a.name +"="+a.value);
//      if (ta && ta.value)
//      debug("(" +ta.value+")");
      if ("class" == a.name)
        targetDom.className = a.nodeValue;
      else if ("style" == a.name)
        targetDom.style.cssText = a.nodeValue;
      else 
        targetDom.setAttribute(a.name, a.value);
      if ("checked" == a.name)
        targetDom.defaultChecked = true;
    }
  }
  // copy or create new child nodes
  var targetDoc = targetDom.ownerDocument;
  var childNodes = this.dom.childNodes;
  var targetChildNodes = targetDom.childNodes;
  for(i = 0; i < childNodes.length; ++i) {
    var n = childNodes[i];
//      debug("n["+i+"] " +n.nodeName);
    if (i >= targetChildNodes.length) {
      targetDom.appendChild(Doc(targetDoc).importNode(n, true));
//      debug("create " +n.nodeName);
      continue;
    }
    var t = targetChildNodes[i];
    if (n.nodeType == 1) {
      // Node.ELEMENT_NODE
      if (n.nodeName.toLowerCase() == t.nodeName.toLowerCase()) {
        Dom(n).merge(t);
      }
      else {
        targetDom.replaceChild(Doc(targetDoc).importNode(n, true), t);
//      debug("replace "+t.nodeName+" with " +n.nodeName+" ("+t.id+":"+n.id+")");
      }
    }
    else if (n.nodeType == 3) {
      // Node.TEXT_NODE
      if (t.nodeType != 3) {
        targetDom.replaceChild(targetDoc.createTextNode(n.nodeValue), t);
//      debug("replace "+t.nodeName+" with '" +n.nodeValue+"'");
        // IE likes this...
        targetDom.innerHTML = targetDom.innerHTML;
      }
      else if (n.nodeValue != t.nodeValue) {
//      debug("text '" +t.nodeValue+"' '"+n.nodeValue+"'");
        t.nodeValue = n.nodeValue;
        // IE likes this...
        targetDom.innerHTML = targetDom.innerHTML;
      }
    }
    else {
      targetDom.replaceChild(Doc(targetDoc).importNode(n, true), t);
//      debug("replace2 "+t.nodeName+" with " +n.nodeName);
        targetDom.innerHTML = targetDom.innerHTML;
    }
  }
}


livcos.HistoryGridPanel = function(config) {
  config.columns = [
    {header: "Time", width: 140, sortable: true, dataIndex: 'time'},
    {header: "ID", width: 200, sortable: true, dataIndex: 'id'}
  ];
  config.stripeRows = true;
  Ext.grid.GridPanel.superclass.constructor.call(this, config);
  var sm = this.getSelectionModel();
  sm.on('rowselect', function(sm, index, record) {
    this.preview.show(record.get("id"));
  }, this);
}
Ext.extend(livcos.HistoryGridPanel, Ext.grid.GridPanel);

livcos.HistoryGridPanel.prototype.selectRow = function(index) {
  var sm = this.getSelectionModel();
  sm.selectRow(index);
}


livcos.HistoryPreviewPanel = function(config) {
	config.contentEl = config.iframeId;
  Ext.Panel.superclass.constructor.call(this, config);
  this.iframeEl = Ext.get(this.contentEl);
  this.iframeEl.on("load", function(evn){
    if (this.hideScrollBars)
      this.iframeEl.dom.contentWindow.document.documentElement.style.overflow = "hidden";
    this.previewLink.update();
  }, this);
};
Ext.extend(livcos.HistoryPreviewPanel, Ext.Panel);

livcos.HistoryPreviewPanel.prototype.show = function(revisionId) {
	var query = ((viewLink.indexOf("?") < 0)?"?":"&") + "_rev=" + revisionId + "&incl-editor=0";
  this.iframeEl.dom.src = viewLink + query;
}



Ext.onReady(function() {
  //Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
  
  var p1 = new livcos.HistoryPreviewPanel({
    border: false,
    columnWidth: .5,
    iframeId: 'preview1',
    hideScrollBars: true
  });
  
  var p2 = new livcos.HistoryPreviewPanel({
    border: false,
    columnWidth: .5,
    iframeId: 'preview2'
  });

  var previewLink = new livcos.HistoryPreviewLink(p1, p2);

  var h1 = new livcos.HistoryGridPanel({
    columnWidth: .5,
    border: false,
    store: store1,
    preview: p1
  });
        
  var h2 = new livcos.HistoryGridPanel({
    columnWidth: .5,
    border: false,
    store: store2,
    preview: p2
  });
        
  new Ext.Viewport({
      layout: 'border',
      items: [{
          region: 'north',
          contentEl: 'header',
          border: false
        }, {
          region: 'center',
          layout: 'column',
          border: false,
          items: [ h1,{html: '', border: false, width: 10}, h2]
        }, {
          region: 'south',
          layout: 'column',
          split: true,
          border: false,
          height: 300,
          minHeight: 100,
          items: [p1,{html: '',border: false,width: 10},p2]
      }]
  });
  
  h1.selectRow(0);
  h2.selectRow(2);
});


